package com.ayf.payment.game.api.channel.zhifuyun;

import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.channel.zhifuyun.req.ZFYAccountCreateReq;
import com.ayf.payment.game.api.channel.zhifuyun.req.ZFYChangeBankAccountReq;
import com.ayf.payment.game.api.channel.zhifuyun.req.ZFYQueryAccountStateReq;
import com.ayf.payment.game.api.channel.zhifuyun.res.ZFYAccountCreateRes;
import com.ayf.payment.game.api.channel.zhifuyun.res.ZFYChangeBankAccountRes;
import com.ayf.payment.game.api.channel.zhifuyun.res.ZFYQueryAccountStateRes;
import com.ayf.payment.game.api.channel.zhifuyun.util.ZFYHttpRes;
import com.ayf.payment.game.api.channel.zhifuyun.util.ZFYHttpUtil;
import com.ayf.payment.game.api.dto.platform.PaymentChannelDTO;
import com.ayf.payment.game.api.utils.Md5Utils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;

import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author: zh-liang
 * @Date: 2022-08-16 15:09
 */
public class ZhiFuYunMerchantUtil {

    private static final String ACCOUNT_CREATE_URL = "/api/VirtualAccount/VirtualAccoutCreate";
    private static final String QUERY_ACCOUNT_STATE_URL = "/api/VirtualAccount/VirtualAccoutState";
    private static final String CHANGE_BANK_ACCOUNT_URL = "/api/VirtualAccount/VirtualChangeBankAccount";

    public static ZFYAccountCreateRes accountCreate(ZFYAccountCreateReq req, PaymentChannelDTO channelDTO) {
        String traceId = req.getTraceId() + " 支付云-个人开户";
        ZFYAccountCreateRes res = new ZFYAccountCreateRes();
        String merId = channelDTO.getAccountNumber();
        String key = channelDTO.getChannelKey();
        String channelPayUrl = channelDTO.getPlatformPublicKey();
        if (channelPayUrl.endsWith("/")) {
            channelPayUrl = channelPayUrl.substring(0, channelPayUrl.lastIndexOf("/"));
        }
        String url = channelPayUrl + ACCOUNT_CREATE_URL;
        String notifyURL = channelDTO.getReturnUrl();
        if (notifyURL.endsWith("/")) {
            notifyURL = notifyURL.substring(0, notifyURL.lastIndexOf("/"));
        }
        notifyURL = notifyURL + "/gameapip/n/zfy/merchant/notify";
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("MerId", merId);
        params.put("ThirdUserID", req.getThirdUserID());
        params.put("UserName", req.getUserName());
        params.put("IdentificationCard", req.getIdentificationCard());
        params.put("Mobile", req.getMobile());
        params.put("BankName", req.getBankName());
        params.put("BankAccount", req.getBankAccount());
        params.put("NotifyURL", notifyURL);
        params.put("Timestamp", System.currentTimeMillis());
        params.put("Version", "1.0");
        String sign = sign(traceId, params, key);
        params.put("Sign", sign);
        try {
            ZFYHttpRes httpRes = ZFYHttpUtil.doPostFrom(traceId, url, params);
            if (!httpRes.isSuccess()) {
                return res;
            }
            JSONObject httpResponse = httpRes.getHttpResponse();
            String code = httpResponse.getString("Code");
            String message = httpResponse.getString("Message");
            String resSign = httpResponse.getString("Sign");
            String uniqueId = httpResponse.getString("UniqueId");
            LinkedHashMap<String, Object> resData = new LinkedHashMap<>();
            resData.put("MerId", httpResponse.getString("MerId"));
            resData.put("ThirdUserID", httpResponse.getString("ThirdUserID"));
            resData.put("UniqueId", uniqueId);
            resData.put("UserName", httpResponse.getString("UserName"));
            resData.put("IdentificationCard", httpResponse.getString("IdentificationCard"));
            resData.put("Mobile", httpResponse.getString("Mobile"));
            resData.put("BankName", httpResponse.getString("BankName"));
            resData.put("BankAccount", httpResponse.getString("BankAccount"));
            resData.put("Status", httpResponse.getString("Status"));
            //resData.put("StatusMessage", httpResponse.getString("StatusMessage"));
            resData.put("Code", code);
            resData.put("Message", message);
            if (!"10000".equals(code)) {
                res.setFailCode(code);
                res.setFailMsg(message);
                return res;
            }
            boolean validaSign = validaSign(traceId + " 验签", resData, key, resSign);
            if (!validaSign) {
                res.setFailCode(code);
                res.setFailMsg("验签失败");
                return res;
            }
            res.setSuccess(true);
            res.setUniqueId(uniqueId);
        } catch (Exception e) {
            LogPortal.error("{} 发生 {} 异常，异常信息为：{}", traceId, e.getClass().getSimpleName(), e.getMessage());
            res.setFailCode("Exception");
            res.setFailMsg(traceId + " 发生 " + e.getClass().getSimpleName() + " 异常");
        }
        return res;
    }

    public static ZFYQueryAccountStateRes queryAccountState(ZFYQueryAccountStateReq req, PaymentChannelDTO channelDTO) {
        String traceId = req.getTraceId() + " 支付云-个人开户状态查询";
        ZFYQueryAccountStateRes res = new ZFYQueryAccountStateRes();
        String merId = channelDTO.getAccountNumber();
        String key = channelDTO.getChannelKey();
        String channelPayUrl = channelDTO.getPlatformPublicKey();
        if (channelPayUrl.endsWith("/")) {
            channelPayUrl = channelPayUrl.substring(0, channelPayUrl.lastIndexOf("/"));
        }
        String url = channelPayUrl + QUERY_ACCOUNT_STATE_URL;
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("MerId", merId);
        params.put("ThirdUserID", req.getThirdUserID());
        params.put("Timestamp", System.currentTimeMillis());
        params.put("Version", "1.0");
        String sign = sign(traceId, params, key);
        params.put("Sign", sign);
        try {
            ZFYHttpRes httpRes = ZFYHttpUtil.doPostFrom(traceId, url, params);
            if (!httpRes.isSuccess()) {
                return res;
            }
            JSONObject httpResponse = httpRes.getHttpResponse();
            String code = httpResponse.getString("Code");
            String message = httpResponse.getString("Message");
            String resSign = httpResponse.getString("Sign");
            String Status = httpResponse.getString("Status");
            String StatusMessage = httpResponse.getString("StatusMessage");
            LinkedHashMap<String, Object> resData = new LinkedHashMap<>();
            resData.put("MerId", httpResponse.getString("MerId"));
            resData.put("ThirdUserID", httpResponse.getString("ThirdUserID"));
            resData.put("Status", Status);
            //resData.put("StatusMessage", StatusMessage);
            resData.put("Code", code);
            resData.put("Message", message);
            if (!"10000".equals(code)) {
                res.setFailCode(code);
                res.setFailMsg(message);
                return res;
            }
            boolean validaSign = validaSign(traceId + " 验签", resData, key, resSign);
            if (!validaSign) {
                res.setFailCode(code);
                res.setFailMsg("验签失败");
                return res;
            }
            res.setStatus(Status);
            res.setStatusMsg(StatusMessage);
            res.setSuccess(true);
        } catch (Exception e) {
            LogPortal.error("{} 发生 {} 异常，异常信息为：{}", traceId, e.getClass().getSimpleName(), e.getMessage());
            res.setFailCode("Exception");
            res.setFailMsg(traceId + " 发生 " + e.getClass().getSimpleName() + " 异常");
        }
        return res;
    }
    public static ZFYChangeBankAccountRes changeBankAccount(ZFYChangeBankAccountReq req, PaymentChannelDTO channelDTO) {
        String traceId = req.getTraceId() + " 支付云-个人用户换卡";
        ZFYChangeBankAccountRes res = new ZFYChangeBankAccountRes();
        String merId = channelDTO.getAccountNumber();
        String key = channelDTO.getChannelKey();
        String channelPayUrl = channelDTO.getPlatformPublicKey();
        if (channelPayUrl.endsWith("/")) {
            channelPayUrl = channelPayUrl.substring(0, channelPayUrl.lastIndexOf("/"));
        }
        String url = channelPayUrl + CHANGE_BANK_ACCOUNT_URL;
        String notifyURL = channelDTO.getReturnUrl();
        if (notifyURL.endsWith("/")) {
            notifyURL = notifyURL.substring(0, notifyURL.lastIndexOf("/"));
        }
        notifyURL = notifyURL + "/gameapip/n/zfy/merchant/notify";
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("MerId", merId);
        params.put("ThirdUserID", req.getThirdUserID());
        params.put("UserName", req.getUserName());
        params.put("IdentificationCard", req.getIdentificationCard());
        params.put("Mobile", req.getMobile());
        params.put("BankName", req.getBankName());
        params.put("BankAccount", req.getBankAccount());
        params.put("NotifyURL", notifyURL);
        params.put("Timestamp", System.currentTimeMillis());
        params.put("Version", "1.0");
        String sign = sign(traceId, params, key);
        params.put("Sign", sign);
        try {
            ZFYHttpRes httpRes = ZFYHttpUtil.doPostFrom(traceId, url, params);
            if (!httpRes.isSuccess()) {
                return res;
            }
            JSONObject httpResponse = httpRes.getHttpResponse();
            String code = httpResponse.getString("Code");
            String message = httpResponse.getString("Message");
            String resSign = httpResponse.getString("Sign");
            LinkedHashMap<String, Object> resData = new LinkedHashMap<>();
            resData.put("MerId", httpResponse.getString("MerId"));
            resData.put("ThirdUserID", httpResponse.getString("ThirdUserID"));
            resData.put("UniqueId", httpResponse.getString("UniqueId"));
            resData.put("NewUserName", httpResponse.getString("NewUserName"));
            resData.put("NewMobile", httpResponse.getString("NewMobile"));
            resData.put("NewBankName", httpResponse.getString("NewBankName"));
            resData.put("NewBankNo", httpResponse.getString("NewBankNo"));
            resData.put("Status", httpResponse.getString("Status"));
            resData.put("StatusMessage", httpResponse.getString("StatusMessage"));
            resData.put("Code", code);
            resData.put("Message", message);
            if (!"10000".equals(code)) {
                res.setFailCode(code);
                res.setFailMsg(message);
                return res;
            }
            boolean validaSign = validaSign(traceId + " 验签", resData, key, resSign);
            if (!validaSign) {
                res.setFailCode(code);
                res.setFailMsg("验签失败");
                return res;
            }
            res.setSuccess(true);
        } catch (Exception e) {
            LogPortal.error("{} 发生 {} 异常，异常信息为：{}", traceId, e.getClass().getSimpleName(), e.getMessage());
            res.setFailCode("Exception");
            res.setFailMsg(traceId + " 发生 " + e.getClass().getSimpleName() + " 异常");
        }
        return res;
    }

    public static String sign(String traceId, LinkedHashMap<String, Object> params, String key) {
        AtomicReference<String> str = new AtomicReference<>("");
        params.forEach((k, v) -> str.updateAndGet(v1 -> v1 + v));
        String s1 = str.get() + "|" + key;
        LogPortal.info("{} 签名之前字符串为：{}", traceId, s1);
        String s2 = Md5Utils.encode(s1).toUpperCase();
        LogPortal.info("{} 签名之后字符串为：{}", traceId, s2);
        return s2;
    }

    public static boolean validaSign(String traceId, LinkedHashMap<String, Object> params, String key, String resSign) {
        String sign = sign(traceId, params, key);
        if (resSign.equals(sign)) {
            LogPortal.info("{} 验签成功", traceId);
            return true;
        }
        LogPortal.error("{} 验签失败", traceId);
        return false;
    }

    private static JSONObject getRouteConfig() {
        JSONObject route = new JSONObject();
        route.put("MerId", "1000019");
        route.put("key", "78A46EB8AAE1558DD54DC8D24D87FAF1");
        route.put("NotifyURL", "https://test.com");
        return route;
    }

    private static void accountCreateTest() {
        ZFYAccountCreateReq req = new ZFYAccountCreateReq();
        req.setThirdUserID("202054201AS");
        req.setUserName("张三");
        req.setIdentificationCard("350781196403076303");
        req.setMobile("15201315520");
        req.setBankName("中国银行");
        req.setBankAccount("1212");

        req.setTraceId(SnowFlakeUtils.getUniqueId());
        PaymentChannelDTO channelDTO=new PaymentChannelDTO();
        accountCreate(req, channelDTO);
    }

    public static void main(String[] args) {
        accountCreateTest();
    }
}
